﻿using AutoMapper;
using InitQ.Cache;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using SkiaSharp;
using Smart.Admin.Domain.Common;
using Smart.Admin.Domain.Model.Config;
using Smart.Admin.Domain.Model.Const;
using Smart.Admin.Domain.Model.Entity;
using Smart.Admin.Domain.Model.Enum;
using Smart.Admin.Domain.Model.Request.Account;
using Smart.Admin.Domain.Model.Request.Department;
using Smart.Admin.Domain.Model.Request.Employee;
using Smart.Admin.Domain.Model.Response;
using Smart.Admin.Domain.Model.Response.Account;
using Smart.Admin.Domain.Model.Response.Department;
using Smart.Admin.Domain.Model.Response.Employee;
using Smart.Admin.Domain.Model.Response.Menu;
using Smart.Admin.Domain.Repository;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Smart.Admin.Domain.Service
{
    /// <summary>
    /// 员工服务
    /// </summary>
    public class EmployeeService:EmployeeExtensions
    {
        private readonly SmartAdminDbContext _context;
        private readonly ICacheService _redisService;
        private readonly IOptions<JwtOptions> _options;
        private readonly IMapper _mapper;
        public EmployeeService(SmartAdminDbContext context, ICacheService redisService, IOptions<JwtOptions> options, IMapper mapper)
        {
            _context = context;
            _redisService = redisService;
            _options = options;
            _mapper = mapper;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<JsonResponse<LoginResponse>> Login(LoginRequest request) 
        {
            try
            {
                var code = await _redisService.GetAsync<string>(string.Format(RedisMapp.smart_admin_sys_login_imgcode, request.ImgId));
                if (request.Code.ToLower() != code) return JsonResult.Error<LoginResponse>(message: "验证码错误");
                //密码使用md5
                var pwd =  EncryptHelper.Md5Hash(request.Password, "utf-8");
                var model = await _context.Employee.AsNoTracking().FirstOrDefaultAsync(m=>m.Pwd == pwd && (m.Account == request.LoginName || m.Phone == request.LoginName));
                if(model == null) return JsonResult.Error<LoginResponse>(message: "账号或密码错误");
                if(model.Status != (int)PubStatus.Open) return JsonResult.Error<LoginResponse>(message: "账号已被禁用");

                //获取用户部门
                var department = await _context.Department.FirstOrDefaultAsync(m => m.Id == model.DepartmentId);


                //获取用户菜单
                var roleMenu = new List<MenuResponse>();
                if (model.IsAdmin)
                {
                    roleMenu = await GetAllRoleMenu();
                }
                else
                {
                    roleMenu = await GetRoleMenu(model.Id);
                }
                //秘钥，就是标头，这里用Hmacsha256算法，需要256bit的密钥
                var securityKey = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Value.Secret)), SecurityAlgorithms.HmacSha256);
                //相当于有效载荷
                var claims = new Claim[] {
                new Claim(JwtRegisteredClaimNames.Iss,_options.Value.Iss),
                new Claim(JwtRegisteredClaimNames.Aud,_options.Value.Aud),
                new Claim("Phone",model.Phone.ToString()),
                new Claim("Id",model.Id.ToString()),
                new Claim("Name",model.Name),
                };
                SecurityToken securityToken = new JwtSecurityToken(
                    signingCredentials: securityKey,
                    expires: DateTime.Now.AddDays(1),//过期时间
                    claims: claims
                );
                //生成jwt令牌
                var jwtToken = new JwtSecurityTokenHandler().WriteToken(securityToken);

                return JsonResult.Success(new LoginResponse() 
                {
                    EmployeeId = model.Id,
                    Phone = model.Phone,
                    Token = jwtToken,
                    UserId = model.Id,
                    UserName = model.Name,
                    DepartmentId = model.DepartmentId,
                    DepartmentName = department?.Name,
                    MenuList = roleMenu,
                    IsAdmin = model.IsAdmin,
                });
            }
            catch (Exception ex)
            {
                return JsonResult.Error<LoginResponse>(message: $"系统错误->{ex.Message}|{ex.StackTrace}");
            }
        }

        /// <summary>
        /// 获取登录信息
        /// </summary>
        /// <param name="employeeId"></param>
        /// <returns></returns>
        public async Task<JsonResponse<LoginResponse>> GetLoginInfo()
        {
            try
            {
                var model = await _context.Employee.AsNoTracking().FirstOrDefaultAsync(m=>m.Id.ToString() == EmployeeId);
                if (model == null) return JsonResult.Error<LoginResponse>(message: "登录失效");
                if (model.Status != (int)PubStatus.Open) return JsonResult.Error<LoginResponse>(message: "账号已被禁用");

                //获取用户部门
                var department = await _context.Department.FirstOrDefaultAsync(m => m.Id == model.DepartmentId);


                //获取用户菜单
                var roleMenu = new List<MenuResponse>();
                if (model.IsAdmin)
                {
                    roleMenu = await GetAllRoleMenu();
                }
                else
                {
                    roleMenu = await GetRoleMenu(model.Id);
                }
                //秘钥，就是标头，这里用Hmacsha256算法，需要256bit的密钥
                var securityKey = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Value.Secret)), SecurityAlgorithms.HmacSha256);
                //相当于有效载荷
                var claims = new Claim[] {
                new Claim(JwtRegisteredClaimNames.Iss,_options.Value.Iss),
                new Claim(JwtRegisteredClaimNames.Aud,_options.Value.Aud),
                new Claim("Phone",model.Phone.ToString()),
                new Claim("Id",model.Id.ToString()),
                new Claim("Name",model.Name),
                };
                SecurityToken securityToken = new JwtSecurityToken(
                    signingCredentials: securityKey,
                    expires: DateTime.Now.AddDays(1),//过期时间
                    claims: claims
                );
                //生成jwt令牌
                var jwtToken = new JwtSecurityTokenHandler().WriteToken(securityToken);

                return JsonResult.Success(new LoginResponse()
                {
                    EmployeeId = model.Id,
                    Phone = model.Phone,
                    Token = jwtToken,
                    UserId = model.Id,
                    UserName = model.Name,
                    DepartmentId = model.DepartmentId,
                    DepartmentName = department?.Name,
                    MenuList = roleMenu,
                    IsAdmin = model.IsAdmin,
                });
            }
            catch (Exception ex)
            {
                return JsonResult.Error<LoginResponse>(message: "系统错误");
            }
        }


        /// <summary>
        /// 获取全部员工
        /// </summary>
        /// <returns></returns>
        public async Task<JsonResponse<List<GetAllEmployeeResponse>>> GetAllEmployee() 
        {
            try
            {
                var query =  from employee in _context.Employee
                             join department in _context.Department on employee.DepartmentId equals department.Id
                             where employee.Status ==(int)PubStatus.Open
                             select new GetAllEmployeeResponse() 
                             {
                                 EmployeeId=employee.Id,
                                 IsAdmin=employee.IsAdmin,
                                 ActualName = employee.Name,
                                 Phone = employee.Phone,
                                 DepartmentId = employee.DepartmentId,
                                 DepartmentName=department.Name,
                             };
                var response = await query.ToListAsync();
                return JsonResult.Success(response);
            }
            catch (Exception ex)
            {
                return JsonResult.Error<List<GetAllEmployeeResponse>>(message: "系统错误");
            }
        }



        /// <summary>
        /// 分页查询员工列表
        /// </summary>
        /// <returns></returns>
        public async Task<JsonResponse<List<GetEmployeeResponse>>> GetEmployeePageList(GetEmployeePageListRequest request)
        {
            var response = new JsonResponse<List<GetEmployeeResponse>>();
            try
            {
                //该角色下已存在的员工
                var employeeIds = new List<long>();
                if (request.NotRoleId.HasValue)
                {
                    employeeIds = await _context.RoleEmployee.AsNoTracking().Where(m => m.RoleId == request.NotRoleId).Select(m => m.EmployeeId).ToListAsync();
                }


                var query = from employee in _context.Employee
                            join roleEmployee in _context.RoleEmployee on employee.Id equals roleEmployee.EmployeeId into temp
                            from t in temp.DefaultIfEmpty()
                            join department in _context.Department on employee.DepartmentId equals department.Id
                            where  request.RoleId.HasValue? t.RoleId==request.RoleId.Value:1==1
                            select new GetEmployeeResponse()
                            {
                                EmployeeId = employee.Id,
                                IsAdmin = employee.IsAdmin,
                                Name = employee.Name,
                                Phone = employee.Phone,
                                DepartmentId = employee.DepartmentId,
                                DepartmentName = department.Name,
                                Account=employee.Account,
                                CreateTime=employee.CreateTime,
                                Remark=employee.Remark,
                                Status=employee.Status,
                                UpdateTime=employee.UpdateTime,
                            };
                query = query.WhereIf(employeeIds.Count > 0, p => !employeeIds.Contains(p.EmployeeId));
                query = query.WhereIf(request.Status.HasValue, p => p.Status == request.Status);
                query = query.WhereIf(request.DepartmentId.HasValue, p => p.DepartmentId == request.DepartmentId);
                query = query.WhereIf(!string.IsNullOrEmpty(request.Keyword), p=>p.Name.Contains(request.Keyword)||p.Account.Contains(request.Keyword) || p.Phone.Contains(request.Keyword));
                query = query.Distinct();
                var data = await query.OrderByDescending(m => m.CreateTime).Skip((request.PageIndex - 1) * request.PageSize).Take(request.PageSize).ToListAsync();
                foreach (var item in data)
                {
                    //查询员工角色信息
                    var queryRole = from roleEmployee in _context.RoleEmployee
                             join role in _context.Role on roleEmployee.RoleId equals role.Id
                             where roleEmployee.EmployeeId == item.EmployeeId
                             orderby roleEmployee.Id
                             select role;
                    var employeeRole = await queryRole.ToListAsync();
                    item.RoleIdList = employeeRole.Select(x => x.Id).ToList();
                    item.RoleNameList = employeeRole.Select(x => x.RoleName).ToList();
                }

                response.code = "0";
                response.data = data;
                response.total = await query.CountAsync();
                return response;
            }
            catch (Exception ex)
            {
                return JsonResult.Error<List<GetEmployeeResponse>>(message: "系统错误");
            }
        }




        /// <summary>
        /// 创建员工
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<JsonResponse> CreateEmployee(CreateEmployeeRequest request)
        {
            using (var tran = await _context.Database.BeginTransactionAsync())
            {
                try
                {
                    var bl = await _context.Employee.AnyAsync(m => m.Account == request.Account);
                    if (bl) return JsonResult.Error(message: "登录账号已存在");
                    var model = _mapper.Map<EmployeeEntity>(request);
                    model.Pwd = EncryptHelper.Md5Hash(request.Pwd, "utf-8");
                    model.CreateTime = DateTime.Now;
                    model.UpdateTime = model.CreateTime;
                    await _context.Employee.AddAsync(model);
                    await _context.SaveChangesAsync();
                    //添加用户角色
                    if (request.RoleIdList != null && request.RoleIdList.Count() > 0)
                    {
                        var emploryeeRoles = new List<RoleEmployeeEntity>();
                        foreach (var roleId in request.RoleIdList)
                        {
                            emploryeeRoles.Add(new RoleEmployeeEntity()
                            {
                                RoleId = roleId,
                                EmployeeId = model.Id,
                                CreateTime = DateTime.Now,
                                UpdateTime = DateTime.Now,
                            });
                        }
                        await _context.RoleEmployee.AddRangeAsync(emploryeeRoles);
                        await _context.SaveChangesAsync();
                    }
                    await tran.CommitAsync(); 
                    return JsonResult.Success();
                }
                catch (Exception ex)
                {
                    await tran.RollbackAsync();
                    return JsonResult.Error(message: "系统错误");
                }
            }
        }


        /// <summary>
        /// 修改员工信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<JsonResponse> UpdateEmployee(UpdateEmployeeRequest request)
        {
            try
            {
                var model = await _context.Employee.FirstOrDefaultAsync(m => m.Id == request.EmployeeId);
                if (model == null) return JsonResult.Error(message: "数据不存在");
                if (model.Account != request.Account) return JsonResult.Error(message: "员工账号不允许修改");
                model.Status=request.Status;
                model.Remark=request.Remark;
                model.DepartmentId=request.DepartmentId;
                model.Name=request.Name;
                model.Phone=request.Phone;
                model.UpdateTime = DateTime.Now;
                _context.Employee.Update(model);
                //更新角色
                var emploryeeRoles = await _context.RoleEmployee.AsNoTracking().Where(m => m.EmployeeId == request.EmployeeId).ToListAsync();
                if (emploryeeRoles.Count > 0)
                {
                    _context.RoleEmployee.RemoveRange(emploryeeRoles);
                }
                if (request.RoleIdList != null && request.RoleIdList.Count() > 0)
                {
                    emploryeeRoles = new List<RoleEmployeeEntity>();
                    foreach (var roleId in request.RoleIdList)
                    {
                        emploryeeRoles.Add(new RoleEmployeeEntity()
                        {
                            RoleId = roleId,
                            EmployeeId = model.Id,
                            CreateTime = DateTime.Now,
                            UpdateTime = DateTime.Now,
                        });
                    }
                    await _context.RoleEmployee.AddRangeAsync(emploryeeRoles);
                }

                await _context.SaveChangesAsync();
                return JsonResult.Success();
            }
            catch (Exception ex)
            {
                return JsonResult.Error(message: "系统错误");
            }
        }

        /// <summary>
        /// 删除员工信息
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<JsonResponse> DeleteEmployee(DeleteEmployeeRequest request)
        {
            try
            {
                var list = await _context.Employee.Where(m => request.EmployeeIds.Contains( m.Id)).ToListAsync();
                if (list.Count > 0) 
                {
                    //删除员工角色
                    foreach (var item in list)
                    {
                        var employeeRoles = await _context.RoleEmployee.Where(m => m.EmployeeId == item.Id).ToListAsync();
                        if (employeeRoles.Count > 0) 
                        {
                            _context.RoleEmployee.RemoveRange(employeeRoles);
                        }
                    }
                }
                //删除员工信息
                _context.Employee.RemoveRange(list);
                await _context.SaveChangesAsync();
                return JsonResult.Success();
            }
            catch (Exception ex)
            {
                return JsonResult.Error(message: "系统错误");
            }
        }



        /// <summary>
        /// 修改员工状态
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<JsonResponse> UpdateEmployeeStatus(UpdateEmployeeStatusRequest request)
        {
            try
            {
                var model = await _context.Employee.FirstOrDefaultAsync(m => m.Id == request.EmployeeId);
                if (model == null) return JsonResult.Error(message: "数据不存在");
                if(model.IsAdmin) return JsonResult.Error(message: "管理员状态无法修改");
                model.Status = request.Status;
                await _context.SaveChangesAsync();
                return JsonResult.Success();
            }
            catch (Exception ex)
            {
                return JsonResult.Error(message: "系统错误");
            }
        }

        /// <summary>
        /// 调整员工部门
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<JsonResponse> UpdateEmployeeDepartment(UpdateEmployeeDepartmentRequest request)
        {
            try
            {
                var bl = await _context.Department.AsNoTracking().AnyAsync(m => m.Id == request.DepartmentId);
                if (!bl) return JsonResult.Error(message: "部门不存在");
                var list = await _context.Employee.AsNoTracking().Where(m => request.EmployeeIdList.Contains(m.Id)).ToListAsync();
                foreach (var model in list)
                {
                    if (model.IsAdmin) return JsonResult.Error(message: "管理员部门无法修改");
                    model.DepartmentId = request.DepartmentId;
                }

                if (list.Count() > 0) 
                {
                    _context.Employee.UpdateRange(list);
                    await _context.SaveChangesAsync();
                }
                return JsonResult.Success();
            }
            catch (Exception ex)
            {
                return JsonResult.Error(message: "系统错误");
            }
        }



        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<JsonResponse> UpdateEmployeePassword(UpdateEmployeePasswordRequest request)
        {
            try
            {
                var model = await _context.Employee.FirstOrDefaultAsync(m => m.Id == request.EmployeeId);
                if (model == null) return JsonResult.Error(message: "数据不存在");
                if (model.IsAdmin) return JsonResult.Error(message: "管理员信息无法修改");
                model.Pwd = EncryptHelper.Md5Hash(request.Password, "utf-8");
                await _context.SaveChangesAsync();
                return JsonResult.Success();
            }
            catch (Exception ex)
            {
                return JsonResult.Error(message: "系统错误");
            }
        }


        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<JsonResponse<string>> ResetEmployeePassword(long employeeId)
        {
            try
            {
                var model = await _context.Employee.FirstOrDefaultAsync(m => m.Id == employeeId);
                if (model == null) return JsonResult.Error<string>(message: "数据不存在");
                if (model.IsAdmin) return JsonResult.Error<string>(message: "管理员信息无法修改");
                var newPwd = Guid.NewGuid().ToString("N").Substring(0,8);
                model.Pwd = EncryptHelper.Md5Hash(newPwd, "utf-8");
                await _context.SaveChangesAsync();
                return JsonResult.Success<string>(newPwd);
            }
            catch (Exception ex)
            {
                return JsonResult.Error<string>(message: "系统错误");
            }
        }


        /// <summary>
        /// 获取用户角色的所有菜单
        /// </summary>
        /// <returns></returns>
        private async Task<List<MenuResponse>> GetRoleMenu(long employeeId) 
        {
            var query = from employee in _context.Employee
                        join roleEmployee in _context.RoleEmployee on employee.Id equals roleEmployee.EmployeeId
                        join roleMenu in _context.RoleMenu on roleEmployee.RoleId equals roleMenu.RoleId
                        join menu in _context.Menu on roleMenu.MenuId equals menu.Id
                        orderby menu.Sort
                        where employee.Id == employeeId  && !menu.DisabledFlag && !menu.DeletedFlag
                        select new MenuResponse() 
                        {
                            FrameFlag = menu.FrameFlag,
                            FrameUrl = menu.FrameUrl,
                            CacheFlag = menu.CacheFlag,
                            DisabledFlag = menu.DisabledFlag,
                            VisibleFlag = menu.VisibleFlag,
                            ApiPerms = menu.ApiPerms,
                            Component = menu.Component,
                            ContextMenuId = menu.ContextMenuId,
                            Icon = menu.Icon,
                            MenuId =menu.Id,
                            MenuName=menu.MenuName,
                            MenuType=menu.MenuType,
                            ParentId=menu.ParentId,
                            Path = menu.Path,
                            PermsType = menu.PermsType,
                            Sort=menu.Sort,
                            WebPerms=menu.WebPerms,
                        };
            var list = await query.ToListAsync();
            return list;
        }

        /// <summary>
        /// 管理员获取全部菜单
        /// </summary>
        /// <returns></returns>
        private async Task<List<MenuResponse>> GetAllRoleMenu() 
        {
            var query = from menu in _context.Menu
                        orderby menu.Sort
                        where !menu.DisabledFlag && !menu.DeletedFlag
                        select new MenuResponse()
                        {
                            FrameFlag = menu.FrameFlag,
                            FrameUrl = menu.FrameUrl,
                            CacheFlag = menu.CacheFlag,
                            DisabledFlag = menu.DisabledFlag,
                            VisibleFlag = menu.VisibleFlag,
                            ApiPerms = menu.ApiPerms,
                            Component = menu.Component,
                            ContextMenuId = menu.ContextMenuId,
                            Icon = menu.Icon,
                            MenuId = menu.Id,
                            MenuName = menu.MenuName,
                            MenuType = menu.MenuType,
                            ParentId = menu.ParentId,
                            Path = menu.Path,
                            PermsType = menu.PermsType,
                            Sort = menu.Sort,
                            WebPerms = menu.WebPerms,
                        };
            var list = await query.ToListAsync();
            return list;
        }
    }
}
